#pragma once
#include <mutex>

namespace wzh
{
	template <typename T>
	class SharedPtr
	{
	public:
		SharedPtr(T* ptr)
			:_ptr(ptr), _mtx(new std::mutex), _count(new int(1))
		{}

		SharedPtr(SharedPtr<T>& sptr)
			:_ptr(sptr._ptr), _count(sptr._count), _mtx(sptr._mtx)
		{
			AddCount();
		}
		~SharedPtr()
		{
			SubCount();
		}
		void AddCount()
		{
			_mtx->lock();
			(*_count)++;
			_mtx->unlock();
		}
		void SubCount()
		{
			_mtx->lock();
			bool flag = false;
			(*_count)--;
			if (*_count <= 0 && _ptr)
			{
				delete _ptr;
				delete _count;
				_ptr = nullptr;
				flag = true;
			}
			_mtx->unlock();
			if (flag) delete _mtx;
		}

		T* operator->()
		{
			return _ptr;
		}
		T& operator*()
		{
			return *_ptr;
		}
		SharedPtr<T>& operator=(SharedPtr<T>& sptr)
		{
			if (this != &sptr)
			{
				SubCount();
				_ptr = sptr._ptr;
				_count = sptr._count;
				_mtx = sptr._mtx;
				AddCount();
			}
			return *this;
		}
	private:
		T* _ptr;
		int* _count;
		std::mutex* _mtx;
	};
}